﻿import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.Hour;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.ui.RectangleInsets;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

public class ChartEngine {
    TimeSeriesCollection dataset = null;
    private String title = "Title";
    private String xAxisName = "Price, $";
    private String yAxisName = "Month";
    private Boolean baseShapesVisible = false;
    private Boolean baseShapesFilled = false;


    JFreeChart  createChart() {
        JFreeChart chart = ChartFactory.createTimeSeriesChart(
                title,  // title
                xAxisName,             // x-axis label
                yAxisName,   // y-axis label
                dataset,            // data
                true,               // create legend?
                true,               // generate tooltips?
                false               // generate URLs?
        );

        chart.setBackgroundPaint(Color.white);
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
        plot.setDomainCrosshairVisible(true);
        plot.setRangeCrosshairVisible(true);

        XYItemRenderer r = plot.getRenderer();
        if (r instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
            renderer.setBaseShapesVisible(baseShapesVisible);
            renderer.setBaseShapesFilled(baseShapesFilled);
        }

        DateAxis axis = (DateAxis) plot.getDomainAxis();
        axis.setDateFormatOverride(new SimpleDateFormat("dd-MMM-yyyy"));
       return chart;
    }

    public void fillDataset(Map<String, List<Map>> dataList, String setName, String categoryName, String itemName, String valueName) {
        dataset = new TimeSeriesCollection();
        TimeSeries s = null;
        Set keys = dataList.keySet();
        Double dataValue = 0d;
        int setIntValue = 0;
        int categoryIntValue = 0;
        int itemIntValue = 0;

        for (Object key : keys) {
            List<Map> datasetList = dataList.get(key.toString());

            s = new TimeSeries(key.toString(), Day.class);
            for (Map map : datasetList) {
                Object setDbValue = null;
                Object categoryDbValue = null;
                Object itemDbValue = null;
                Object dataDbValue = null;

                setDbValue = map.get(setName);
                categoryDbValue = map.get(categoryName);
                itemDbValue = map.get(itemName);
                dataDbValue = map.get(valueName);

                if (setDbValue != null) {
                    try {
                        setIntValue = Integer.parseInt(setDbValue.toString());
                    } catch (Exception e) {
                    }
                }
                //System.out.println(setIntValue+"--"+setDbValue instanceof String);
                if (categoryDbValue != null)
                    try {
                        categoryIntValue = Integer.parseInt(categoryDbValue.toString());
                    } catch (Exception e) {
                    }

                if (itemDbValue != null)
                    try {
                        itemIntValue = Integer.parseInt(itemDbValue.toString());
                    } catch (Exception e) {
                    }
                if (dataDbValue != null)
                    try {
                        dataValue = Double.parseDouble(dataDbValue.toString());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                System.out.println("year:"+setIntValue+" - month:"+categoryIntValue+" - day:"+itemIntValue+" - value:"+dataValue);
                s.add(new Day(itemIntValue, categoryIntValue, setIntValue), dataValue);
            }
            if (s != null)
                dataset.addSeries(s);
        }

    }

    public void convertToDataSet(String label, List dataList) {
        dataset = new TimeSeriesCollection();
        TimeSeries s = new TimeSeries(label, Hour.class);
        TimeSeries removed = null;
        List<Map> priceStatistic = new ArrayList<Map>();
        Integer lastState = null;
        Date lastDate = null;
        for (Object aDataList : dataList) {
            Map data = (Map) aDataList;
            Integer state = (Integer) data.get("state");
            Double price = (Double) data.get("priceValue");
            Date date = (Date) data.get("date");
            Calendar cal = new GregorianCalendar();
            cal.setTime(date);
            System.out.println("!" + state + "--" + price + "--" + date);
            switch (state) {
                case 0:
                    if (lastState != null && lastDate != null && lastDate.compareTo(date) < 0) {
                        Calendar lastCal = new GregorianCalendar();
                        lastCal.setTime(lastDate);
                        s.add(new Hour(date), price);
                        break;
                    }
                case -1:
                    if (lastState != null && lastDate != null && lastDate.compareTo(date) < 0) {
                        removed = new TimeSeries("removed", Hour.class);
                        removed.add(new Hour(date), price);
                        dataset.addSeries(removed);
                        s.add(new Hour(date), price);
                    }
                    break;

                case 1:
                    if (lastState != null && removed != null && lastState < 0 ){
                        removed.add(new Hour(date), price);
                    }
                    s.add(new Hour(date), price);
                    break;
            }
            lastState = state;
            lastDate = date;

        }
        dataset.addSeries(s);
    }

    

    public BufferedImage getChartImage(int width, int height){
        JFreeChart chart = createChart();
        return chart.createBufferedImage(width, height);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getXAxisName() {
        return xAxisName;
    }

    public void setXAxisName(String xAxisName) {
        this.xAxisName = xAxisName;
    }

    public String getYAxisName() {
        return yAxisName;
    }

    public void setYAxisName(String yAxisName) {
        this.yAxisName = yAxisName;
    }

    public Boolean getBaseShapesVisible() {
        return baseShapesVisible;
    }

    public void setBaseShapesVisible(Boolean baseShapesVisible) {
        this.baseShapesVisible = baseShapesVisible;
    }

    public Boolean getBaseShapesFilled() {
        return baseShapesFilled;
    }

    public void setBaseShapesFilled(Boolean baseShapesFilled) {
        this.baseShapesFilled = baseShapesFilled;
    }


}
